package com.cyx.netty.gateway.config;
/*
 * Copyright 2013-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import com.cyx.netty.gateway.handler.ServiceChannelInboundHandlerAdapter;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = "classpath:/netty.properties")
public class NettyConfig {

    @Value("${netty.port}")
    private int serverPort;
    @Value("${so.keepalive}")
    private boolean keepAlive;
    @Value("${tcp.nodelay}")
    private boolean tcpNodelay;
    @Value("${so.backlog}")
    private int backlog;
    @Value("${maxContentLength}")
    private int maxContentLength;
    @Bean(name = "port")
    public Integer port(){
        return serverPort;
    }

    private ServiceChannelInboundHandlerAdapter httpHandle;
    private NettyEventThreadConfig nettyEventThreadConfig;

    public NettyConfig(
        ServiceChannelInboundHandlerAdapter httpHandle,
        NettyEventThreadConfig nettyEventThreadConfig) {
        this.httpHandle = httpHandle;
        this.nettyEventThreadConfig=nettyEventThreadConfig;
    }

    @Bean(name = "channelInitializer")
    public ChannelInitializer channelInitializer(){
        return new ChannelInitializer() {
            @Override
            protected void initChannel(Channel channel)  {
                ChannelPipeline channelPipeline = channel.pipeline();
                channelPipeline.addLast(new HttpServerCodec());
                channelPipeline.addLast(new HttpObjectAggregator(maxContentLength));
                channelPipeline.addLast(httpHandle);
                channelPipeline.addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS));
                channelPipeline.addLast(new HeartBeatServerHandler());
            }
        };
    }
    @Bean(name = "serverBootstrap")
    public ServerBootstrap serverBootstrap(){

        return new ServerBootstrap().group(
                nettyEventThreadConfig.bossGroup(),nettyEventThreadConfig.workerGroup()).
                channel(NioServerSocketChannel.class).
                handler(new LoggingHandler(LogLevel.INFO)).
                childHandler(channelInitializer()).
                option(ChannelOption.SO_BACKLOG,backlog).
                childOption(ChannelOption.SO_REUSEADDR,true).
                childOption(ChannelOption.TCP_NODELAY,tcpNodelay).
                childOption(ChannelOption.SO_KEEPALIVE,keepAlive);
    }


}
